/******************************************************************************
 * Copyright (C), 2014, BeeIoT Tech. Co., Ltd. 
 * FileName:        SIM900A_api.c
 * Author:          lvxin 
 * Version :        1.0
 * Date:            2014-12-08 15:12:47
 * Description:
 * Function List:   1. -------
 * History:
 * <author>     <time>                <version >  <desc> 
 * lvxin        2014-12-08 15:12:47   1.0         build this moudle 
 *****************************************************************************/

/******************************************************************************
 *  *INCLUDES
 *  */
#include "SIM900A.h"
#include "conv.h"
#include "dev_platform.h"
#include "pdu.h"
#include <string.h>
#include <stdio.h>

/******************************************************************************
 *  *MICROS
 *  */
#define     DIM(x)  (sizeof(x)/sizeof(x[0]))

/******************************************************************************
 *  *TYPEDEFS
 *  */

typedef struct _SIM900A_stat
{
    char CREG;      //网络注册信息 1 已经注册(在网) 0 未注册
    char CSMINS;    //sim卡插入情况  0 未插入 1 已插入
    char COPS;      //运营商信息  1 中国移动  2 中国联通
    char SMS_address[15];                         //消息中心地址
}SIM900A_stat_t;

/******************************************************************************
 *  *EXTERNAL FUNCTIONS
 *  */
#if (PLATFORM == LPC1114)
extern void display_telephone_state(uint8_t tel_state);
extern void FEED_DOG(void);
#endif
#if (PLATFORM == LPC1114)
extern void mdelay (uint32_t time);
#endif
#if (PLATFORM == LIINUX)
/*延时1ms*/
void mdelay (uint32_t ms)
{
    usleep (1000*ms);
}

#endif


/******************************************************************************
 *  *LOCAL VARIABLES
 *  */
static SIM900A_stat_t l_sim_stat = {0};

/******************************************************************************
 *  *FUNCTION DECLARES
 *  */
static int _handle_sim_reg(char *data, int len);
static int _handle_sim_cops(char *str, int len);
static int _handle_sim_insert(char *data, int len);

/******************************************************************************
 *  *LOCAL FUNCTIONS
 *  */

//SIM卡是否插入
static int _handle_sim_insert(char *data, int len)
{
    data = strstr(data, "+CSMINS:");
    if (data != NULL)
    {
        if (*(data + 11) == '0')
        {
            l_sim_stat.CSMINS = 0;
            return -1;
        }
        else
        {
#if (PLATFORM == LINUX)
            DBG_PRINTF ("SIM卡已插入\n");
#endif
            l_sim_stat.CSMINS = 1;
            return 0;
        }
    }
    return -1;
}

//处理SIM网络运营商信息
static int _handle_sim_cops(char *str, int len)
{
    if(strstr (str, "CHINA MOBILE") != NULL)
    {
#if (PLATFORM == LINUX)
        DBG_PRINTF ("中国移动\n");
#endif
        l_sim_stat.COPS = 1;
    }
    else if(strstr (str, "CHN-UNICOM") != NULL)
    {
#if (PLATFORM == LINUX)
        DBG_PRINTF ("中国联通\n");
#endif
        l_sim_stat.COPS = 2;
    }
    else //网络注册失败
    {
#if (PLATFORM == LINUX)
        DBG_PRINTF ("未知网络\n");
#endif
        l_sim_stat.COPS = 0;
    }
    return 0;
}


/*******************************************************************************
 * Function:      handle_rssi_level()
 * Description:   把获得的信号质量字符串转换为rssi等级
 * Calls:         
 * Called By:     SIM900A_get_rssi_level()
 * Input:         None
 * Return:        int 
 * Others:        None
 ******************************************************************************/
static int _handle_rssi_level(char *data, int len)
{
    uint8_t rssi;
    data = strstr(data,"+CSQ:");
    if (data != NULL)
    {
        if (l_sim_stat.CREG == 0)
        {
            return 0;
        }
        rssi = *(data + 6) - '0';
        if (*(data + 7) != ',')
        {
            rssi = rssi * 10 + *(data + 7) - '0';
        }
        if (rssi == 0) //无服务 
        {
            return 0;
        }
        if (rssi >= 1 && rssi <6)
        {
            return 1;
        }
        if (rssi >= 6 && rssi <12)
        {
            return 2;
        }
        if (rssi >= 12 && rssi <18)
        {
            return 3;
        }
        if (rssi >= 18 && rssi <24)
        {
            return 4;
        }
        return 5;
    }
    return 0;
}

/*******************************************************************************
 * Function:      save_SMS_address()
 * Description:   保存SMS中心地址到l_sim_cmdline
 * Calls:         strncpy();
 * Called By:     SIM900A_get_SMS_address()
 * Input:         data  --字符串
 *                len   --字符串长度
 * Return:        None
 * Others:        None 
 ******************************************************************************/
static int _save_SMS_address(char *data, int len)
{
    data = strstr(data, "+CSCA:");
    if (data != NULL)
    {
        strncpy (l_sim_stat.SMS_address, data+8, 14); //取出SMS地址
    }
    return 0;
}

//SIM卡网络注册是否成功
static int _handle_sim_reg(char *data, int len)
{
    data = strstr(data, "+CREG:");
    if (data != NULL && *(data+9) == '1')
    {
        return 0;//网络注册成功
    }
    return 1;//网络注册失败
}






/******************************************************************************
 *  *PUBLIC FUNCTIONS
 *  */


/*******************************************************************************
 * Function:      SIM900A_open()
 * Description:   启动并建立通信
 * Calls:         SIM900A_run()       
 * Called By:     main()
 * Input:         None
 * Return:        0   --打开成功
 *                -1  --打开失败
 * Others:        NONE
 ******************************************************************************/
int SIM900A_api_open(void)
{
#if (PLATFORM == LINUX)
    int ret;
    /*l_sim_cmdline.idle_callback = NULL;*/
    SIM900A_core_init();

    ret = SIM900A_run ("AT\r\n", 2000, NULL, NULL);
    if ((ret != AT_RETURN_OK) && (SIM900A_run ("\x1b", 2000, NULL, NULL) != AT_RETURN_OK))
    {
        return ret;
    }
    return 0;
#endif
#if (PLATFORM == LPC1114)
    int ret;
    /*SIM900A_core_enable_uart_recv();//开启串口接收使能*/
    /*l_sim_cmdline.cmd_callback  = cmd_callback;*/

    SIM900A_core_init();
    /*l_sim_cmdline.idle_callback = NULL;*/

    //复位
    GSM_RESET_LOW();
    mdelay (2);
    GSM_RESET_HIGH();
    mdelay (2);
    GSM_RESET_LOW();
    mdelay (200);
    GSM_POWER_HIGH();  
    mdelay (2500);
    GSM_POWER_LOW();

    mdelay (4000);
    ret = SIM900A_run ("AT\r\n", 2000, NULL, NULL);
    if ((ret != AT_RETURN_OK) && (SIM900A_run ("\x1b", 2000, NULL, NULL) != AT_RETURN_OK))
    {
        
        GSM_POWER_LOW();
        mdelay (1000);
        GSM_POWER_HIGH();
        mdelay (3000);
        GSM_POWER_LOW();
        mdelay (3000);
        ret = SIM900A_run ("AT\r\n", 2000, NULL, NULL);
        if (ret != AT_RETURN_OK)
        {
            display_telephone_state (3);//模块错误
            return -1;
        }
        return 0;
    }
    return 0;
#endif
}


/*******************************************************************************
 * Function:      SIM900A_init()
 * Description:   初始化SIM900A
 * Calls:         SIM900A_sync_time()
 * Called By:     main()
 * Input:         serial --串口
 * Return:        none
 * Others:        NONE
 ******************************************************************************/

#define SIM900A_dirun(x)  SIM900A_run (x, 2000, NULL, _handle_sim_insert)
int SIM900A_api_init()
{
    int ret = -1;
    int timeout = 0; //记录超时时间
    //  int len;
    /*初始化SIM900A模块*/

    SIM900A_dirun ("ATE0\r\n"       ); //关闭命令回显
    SIM900A_dirun ("AT+CSDT=1\r\n"  ); //开启SIM卡检测
    SIM900A_dirun ("AT+CREG=2\r\n"  ); //设置注册网络信息格式
    SIM900A_dirun ("AT+CMGF=0\r\n"  ); //指定信息的输入输出格式为PDU格式
    SIM900A_dirun ("AT+CSMINS=1\r\n"); //提示SIM卡插入或拔出到终端

    do //检测SIM卡
    {
        ret = SIM900A_run ("AT+CSMINS?\r\n", 2000, NULL, _handle_sim_insert); //查询运营商信息
        if (ret == 0) {break;}//网络注册成功
        mdelay (1000);
        timeout ++;
        if (timeout >= 5)
        {

#if (PLATFORM == LINUX)
            DBG_PRINTF ("未检测到SIM卡\n");
#endif
#if (PLATFORM == LPC1114)
            display_telephone_state (1);
#endif

            return -1;
        }
    }
    while (ret != 0 );

    SIM900A_dirun ("AT+CSCS=\"UCS2\"\r\n"   );//设置字符集为UCS2
    SIM900A_dirun ("AT+CLIP=1\r\n"          );//设置来电显示
    SIM900A_dirun ("AT+CNMI=2,2,,1\r\n"     );//来了新信息直接显示到串口，不作存储，仍然打开传送回报。
    SIM900A_dirun ("AT+CSMP=17,167,2,25\r\n");//设置文本模式参数
    SIM900A_dirun ("AT+CALD=1\r\n"          );//删除闹铃1
    SIM900A_dirun ("AT+CALA=\"10:00:00\",1,0\r\n");//设置闹铃1


    do //检测注册网络
    {
        if (l_sim_stat.CSMINS == 0) return -1;
        ret = SIM900A_run ("AT+CREG?\r\n", 2000, NULL, _handle_sim_reg); //查询运营商信息
        if (ret == 0) {break;}//网络注册成功
        mdelay (1000);
        timeout ++;
    }
    while (ret != 0 && timeout <= 60);

    if (ret == 0) //++网络注册成功
    {
        l_sim_stat.CREG = 1;
        SIM900A_run ("AT+COPS?\r\n", 2000, NULL, _handle_sim_cops); //查询运营商信息
#if (PLATFORM == LPC1114)
        timer0Init (); //初始化sim卡注册状态定时检测
#endif
        SIM900A_api_init_SMS_address(); //保存信息中心地址
    }             //--网络注册成功
    else  //++网络注册失败
    {
        l_sim_stat.CREG = 0;
#if (PLATFORM == LINUX)
        DBG_PRINTF ("网络注册失败！\n");
#endif
#if (PLATFORM == LPC1114)
        display_telephone_state (4);
#endif
    }     //--网络注册失败

    DBG_PRINTF ("初始化完成\n----------------------\n");
    return 0;
}

/*******************************************************************************
 * Function:      SIM900A_get_SMS_address()
 * Description:   获取SMS中心地址并保存
 * Calls:         save_SMS_address() 
 * Called By:     SIM900A_init() 
 * Input:         None
 * Return:        0   --执行成功
 * Others:        None 
 ******************************************************************************/
int SIM900A_api_init_SMS_address()
{
    SIM900A_run("AT+CSCS=\"GSM\"\r\n",  2000, NULL, NULL); //设置成GSM编码
    SIM900A_run("AT+CSCA?\r\n", 2000, NULL, _save_SMS_address); //查询短信中心地址
    SIM900A_run("AT+CSCS=\"UCS2\"\r\n", 2000, NULL, NULL); //设置成UCS2编码
    return 0;
}

char * SIM900A_api_get_SMS_address(void)
{
    return l_sim_stat.SMS_address;
}

int SIM900A_api_get_CREG(void)
{
    return l_sim_stat.CREG;
}


int SIM900A_api_get_COPS(void)
{
    return l_sim_stat.COPS;
}



/*******************************************************************************
 * Function:      SIM900A_get_rssi_level()
 * Description:   读取gsm模块信号强度
 * Calls:         SIM900A_run()
 * Called By:     
 * Input:         None
 * Return:        0 --无服务
 *                1 --信号等级1
 *                2 --信号等级2
 *                3 --信号等级3
 *                4 --信号等级4
 *                5 --信号等级5
 * Others:        None
 ******************************************************************************/
int SIM900A_get_rssi_level()
{
    return SIM900A_run("AT+CSQ\r\n", 1000, NULL, _handle_rssi_level);
}











